﻿using CommonDevelop;
using CommonDevelop.DB;
using CommonEngine;
using CommonFP;
using ManageDB;
using ManageDto;
using ManageRepository;
using System;
using System.Collections.Generic;
using System.Linq;

namespace ManageService
{
    /// <summary>
    /// 部门服务层接口
    /// </summary>
    public interface IDeptService : IBaseService<Base_Dept>
    {
        /// <summary>
        /// 通过机构ID取部门视图集合
        /// </summary>
        IEnumerable<DeptDto> GetDeptByCompanyId(string companyId);
        IEnumerable<DeptDto> GetDeptByCompanyId(string companyId, string keyword);
        List<TreeModel> GetDeptTree(string companyId, string parentId);

        /// <summary>
        /// 在业务层，确认业务行为，取组织公司数据
        /// </summary>
        IEnumerable<CompanyDto> GetCompany();
        Base_Company GetCompany(object keyValue);
        ComDeptDto GetDeptItem(string id);
    }

    /// <summary>
    /// 部门服务层
    /// </summary>
    public class DeptService : BaseService<Base_Dept, IDeptRepository>, IDeptService
    {
        private ICompanyRepository repository_com;
        /// <summary>
        /// 构造注入
        /// </summary>
        public DeptService(IDeptRepository repository, ICompanyRepository comRep)
            : base(repository)
        {
            this.repository_com = comRep;
        }

        public override string BuildSeq()
           => SugarBizDB.BuildSeq_01("Dept");

        public IEnumerable<DeptDto> GetDeptByCompanyId(string companyId)
        {
            var pipe1 = FP.MakePipe<string, Base_Company>(cid => FP.Async(this.repository_com.GetEntity(cid)));
            var pipe2 = FP.MakePipe<string, IEnumerable<Base_Dept>>(cid => FP.Async(this.repository_DB.GetDeptsByCompanyId(cid)));
            var pipe3 = FP.MakePipe<IEnumerable<Base_Dept>, IEnumerable<DeptDto>>(bd => FP.Async(bd.MapToList<Base_Dept, DeptDto>().AsEnumerable()));
            var v = from cid in FP.Async(companyId.IsValidData())
                    from com in pipe1(cid)
                    from bd in pipe2(cid)
                    from dto in pipe3(bd)
                    let _ = dto.ForEach(a => a.CompanyName = com.FullName)
                    select dto;

            var DtoLs = v.Recover(ex => FP.Error(ex.Message))
                .Result
                .Match(e => Enumerable.Empty<DeptDto>(), a => a);

            var loop = FixedPointFactory.Fix<DeptDto, IEnumerable<DeptDto>, string>(f => (Item, DLs) =>
            {
                if (Item.ParentId.IsEmpty())
                    return "";
                else
                    return DLs.FirstOrDefault(a => a.DeptId == Item.ParentId)
                    .ToOption()
                    .Map(b => b.FullName)
                    .Match(() => "", a => a);
            });
            DtoLs.ForEach(a => a.ParentName = loop(a, DtoLs));
            return DtoLs;
        }

        public IEnumerable<DeptDto> GetDeptByCompanyId(string companyId, string keyword)
        {
            var data = this.GetDeptByCompanyId(companyId);
            if (keyword.IsEmpty())
                return data;
            else
                return data.Where(b => b.FullName.Contains(keyword) || b.DeptCode.Contains(keyword));
        }

        public List<TreeModel> GetDeptTree(string companyId, string parentId)
        {
            try
            {
                if (string.IsNullOrEmpty(companyId))
                    return new List<TreeModel>();

                List<DeptDto> list = this.GetDeptByCompanyId(companyId).ToList();
                List<TreeModel> treeList = new List<TreeModel>();
                foreach (var item in list)
                {
                    TreeModel node = new TreeModel
                    {
                        id = item.DeptId,
                        text = item.FullName,
                        value = item.DeptId,
                        showcheck = false,
                        checkstate = 0,
                        isexpand = true,
                        parentId = item.ParentId.IsEmpty() ? "" : item.ParentId
                    };
                    treeList.Add(node);
                }

                if (string.IsNullOrEmpty(parentId))
                    parentId = "";

                return treeList.ToTree(parentId);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public IEnumerable<CompanyDto> GetCompany()
            => FP.Try(() => this.repository_com.GetList().MapToList<Base_Company, CompanyDto>())
            .Run().Match(e => Enumerable.Empty<CompanyDto>(), a => a);

        public Base_Company GetCompany(object keyValue)
            => FP.Try(() => this.repository_com.GetEntity(keyValue))
            .Run().Match(e => null, a => a);

        public ComDeptDto GetDeptItem(string id)
        {
            if (string.IsNullOrWhiteSpace(id))
                return null;

            var dept = this.GetEntity(id).Result;
            if (dept == null)
            {
                var com = this.GetCompany(id);
                if (com == null)
                    return null;
                else
                    return new ComDeptDto() { ComId = com.CompanyId, ComName = com.FullName };
            }
            else
            {
                var com = this.GetCompany(dept.CompanyId);
                if (com == null)
                    return new ComDeptDto() { DeptId = dept.DeptId, DeptName = dept.FullName };
                else
                    return new ComDeptDto() { ComId = com.CompanyId, ComName = com.FullName, DeptId = dept.DeptId, DeptName = dept.FullName };
            }
        }
    }
}
